﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;


namespace 自定义定时任务.Common
{
    public class HierarchicalTimeWheel
    {
        private class TimerTask
        {
            public Action Task;
            public DateTime ExecuteAt;
        }

        private class TimeWheel
        {
            public readonly int SlotCount;
            public readonly long TickDurationMs;
            public readonly List<TimerTask>[] Slots;
            public int CurrentSlot;
            public readonly TimeWheel UpperWheel; // 上层轮

            public TimeWheel(int slotCount, long tickDurationMs, TimeWheel upperWheel = null)
            {
                SlotCount = slotCount;
                TickDurationMs = tickDurationMs;
                UpperWheel = upperWheel;
                Slots = new List<TimerTask>[slotCount];
                for (int i = 0; i < slotCount; i++)
                    Slots[i] = new List<TimerTask>();
            }

            public bool Add(TimerTask task, long delayMs)
            {
                if (delayMs < TickDurationMs * SlotCount)
                {
                    // 放入当前层
                    int ticks = (int)(delayMs / TickDurationMs);
                    int targetSlot = (CurrentSlot + ticks) % SlotCount;
                    Slots[targetSlot].Add(task);
                    return true;
                }
                else if (UpperWheel != null)
                {
                    // 推到上层
                    return UpperWheel.Add(task, delayMs);
                }
                else
                {
                    // 超出最大范围
                    return false;
                }
            }

            public void Advance(Action<TimerTask> executeCallback)
            {
                var slotTasks = Slots[CurrentSlot];
                Slots[CurrentSlot] = new List<TimerTask>(); // 清空

                foreach (var task in slotTasks)
                {
                    if (DateTime.Now >= task.ExecuteAt)
                        executeCallback(task);
                    else
                        Add(task, (long)(task.ExecuteAt - DateTime.Now).TotalMilliseconds);
                }

                CurrentSlot = (CurrentSlot + 1) % SlotCount;

                // 低层轮转满则触发上层轮
                if (CurrentSlot == 0 && UpperWheel != null)
                    UpperWheel.Advance(executeCallback);
            }
        }

        private readonly TimeWheel _millisecondsWheel;
        private readonly Timer _timer;
        private readonly object _lock = new();

        public HierarchicalTimeWheel()
        {
            // 层级设计：60个槽，每个间隔1s、60s、3600s
            var hours = new TimeWheel(24, 3600_000);
            var minutes = new TimeWheel(60, 60_000, hours);
            var seconds = new TimeWheel(60, 1_000, minutes);
            _millisecondsWheel = seconds;

            _timer = new Timer(Tick, null, 1000, 1000);
        }

        public void AddTask(Action task, TimeSpan delay)
        {
            var timerTask = new TimerTask
            {
                Task = task,
                ExecuteAt = DateTime.Now.Add(delay)
            };

            lock (_lock)
            {
                _millisecondsWheel.Add(timerTask, (long)delay.TotalMilliseconds);
            }
        }

        private void Tick(object state)
        {
            lock (_lock)
            {
                _millisecondsWheel.Advance(t =>
                {
                    Task.Run(() =>
                    {
                        try 
                        { t.Task(); }
                        catch (Exception ex) 
                        { Console.WriteLine($"任务执行失败: {ex.Message}"); }
                    });
                });
            }
        }
    }

}
